﻿using System.Diagnostics;
using Glue;
using Glue.Internals.PrintTool;
using Xunit;

namespace GlueExamples.CompleteExamples
{
    public class FlatteingLargeStructureUsingMappers
    {
        private readonly Mapping<Event, EventInfo> theMapping;


        public FlatteingLargeStructureUsingMappers()
        {
            theMapping = SetUpMapper();
        }

        [Fact]
        public void AssertAllPropertiesMapped()
        {
            theMapping.GetRelationsVerification().AssertAllPropertiesRelated<EventInfo>();
        }

        [Fact]
        public void TestMapping()
        {
            theMapping.GetMapperVerification().AssertMapsCorrectlyTowards(new EventInfo());
        }

        [Fact]
        public void Print()
        {
            var printTool = new PrintTool<Event, EventInfo>(theMapping);
            var report = printTool.GetReport();
            report.SortOnLeftColumn();
            printTool.Print(report,x=>Debug.WriteLine(x));
        }

        internal static Mapping<Event, EventInfo> GetMapper()
        {
            return new FlatteingLargeStructureUsingMappers().SetUpMapper();
        }

        private Mapping<Event, EventInfo> SetUpMapper()
        {
            var mapping = new Mapping<Event, EventInfo>();
            mapping.AutoRelateEqualNames(true);
            mapping.Flatten(x => x.Organizer, GetOrganizerMapping());
            mapping.Flatten(x => x.EntryInfo, GetEntryMapping());
            mapping.Flatten(x => x.Activity, GetActivityMapping());
            mapping.Flatten(x => x.Season, GetSeasonMapping());
            mapping.Flatten(x => x.GetLastDeadLine(), GetDeadlineMapping());
            mapping.Flatten(x => x.ArrangingOrganization, GetArrangingOrganizationMapping());
            return mapping;
        }

        private Mapping<OrgElement, EventInfo> GetArrangingOrganizationMapping()
        {
            var mapping = new Mapping<OrgElement, EventInfo>();
            mapping.RelateTowardsRight(x => x.OrgId, y => y.ArrangingOrganizaionId);
            return mapping;
        }

        private Mapping<Deadline, EventInfo> GetDeadlineMapping()
        {
            var mapping = new Mapping<Deadline, EventInfo>();
            mapping.RelateTowardsRight(x => x.Date, y => y.DeadLine);
            return mapping;
        }

        private Mapping<Season, EventInfo> GetSeasonMapping()
        {
            var mapping = new Mapping<Season, EventInfo>();
            mapping.RelateTowardsRight(x => x.Name, y => y.SeasonName);
            return mapping;
        }

        private Mapping<Activity, EventInfo> GetActivityMapping()
        {
            var mapping = new Mapping<Activity, EventInfo>();
            mapping.RelateTowardsRight(x => x.Name, y => y.ActivityName);
            mapping.RelateTowardsRight(x => x.Id, y => y.ActivityId);
            mapping.RelateTowardsRight(x => x.ParentActivityId, y => y.ParentActivityId);
            return mapping;
        }

        private Mapping<EntryInfo, EventInfo> GetEntryMapping()
        {
            var mapping = new Mapping<EntryInfo, EventInfo>();
            mapping.RelateTowardsRight(x => x.Description, y => y.EntryDescription);
            mapping.RelateTowardsRight(x => x.ContactPersonName, y => y.EntryContactPersonName);
            mapping.Flatten(x => x.Contact, GetEntryContactMapping());
            return mapping;
        }

        private Mapping<Contact, EventInfo> GetEntryContactMapping()
        {
            var mapping = new Mapping<Contact, EventInfo>();
            mapping.RelateTowardsRight(x => x.TelephoneNo1, y => y.EntryContactPhone);
            mapping.RelateTowardsRight(x => x.Email, y => y.EntryContactEmail);
            mapping.RelateTowardsRight(x => x.HomePage, y => y.EntryContactHomePage);
            return mapping;
        }

        private Mapping<EventOrganiser, EventInfo> GetOrganizerMapping()
        {
            var mapping = new Mapping<EventOrganiser, EventInfo>();
            mapping.Flatten(x => x.Contact, GetOrganiserContactMapping());
            mapping.RelateTowardsRight(x => x.OrgName, y => y.OrganizerOrgName);
            return mapping;
        }

        private Mapping<Contact, EventInfo> GetOrganiserContactMapping()
        {
            var mapping = new Mapping<Contact, EventInfo>();
            mapping.RelateTowardsRight(x => x.Email, y => y.OrganizerContactEmail);
            mapping.RelateTowardsRight(x => x.HomePage, y => y.OrganizerContactHomePage);
            mapping.RelateTowardsRight(x => x.TelephoneNo1, y => y.OrganizerContactPhone);
            return mapping;
        }
    }
}
